﻿/*
 #######  ########   ######   #######  ##    ## 
##     ## ##     ## ##    ## ##     ## ###   ## 
##     ## ##     ## ##       ##     ## ####  ## 
##     ## ########  ##       ##     ## ## ## ## 
##     ## ##        ##       ##     ## ##  #### 
##     ## ##        ##    ## ##     ## ##   ### 
 #######  ##         ######   #######  ##    ## 
 */

using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace RoMFramework
{
    public class Console
    {
        public Dictionary<uint, string> NewLines, TotalLines, Temporary;
        public uint LineNumber;
        private object m_Locker = new object();

        /// <summary>
        /// Initialises a Console instance
        /// </summary>
        public Console()
        {
            NewLines = new Dictionary<uint, string>();
            TotalLines = new Dictionary<uint, string>();
        }

        /// <summary>
        /// Creates a new singleton console instance
        /// </summary>
        static Console()
        {
            _instance = new Console();
        }

        /// <summary>
        /// Retrieves lines that have been added since the last update
        /// </summary>
        /// <param name="update">Whether to call the Update method which clears the NewLines dictionary</param>
        /// <returns>A dictionary containing the new lines</returns>
        public Dictionary<uint, string> GetNewLines(bool update)
        {
            lock (m_Locker)
            {
                Temporary = new Dictionary<uint, string>(NewLines);
                if (update)
                {
                    Update();
                }
                return Temporary; 
            }
        }

        /// <summary>
        /// Retrieves lines that have been added since the last update
        /// </summary>
        /// <param name="update">Whether to call the Update method which clears the NewLines dictionary</param>
        /// <returns>A dictionary containing the new lines</returns>
        public static Dictionary<uint, string> GetNewLinesSingleton(bool update)
        {
            return Instance.GetNewLines(update);
        }

        /// <summary>
        /// Adds all the lines in the New Lines dictionary to the Total Lines dictionary and clears New Lines
        /// </summary>
        public void Update()
        {
            lock (m_Locker)
            {
               foreach (KeyValuePair<uint, string> kvp in NewLines)
                {
                    TotalLines.Add(kvp.Key, kvp.Value);
                }
                NewLines.Clear(); 
            }
            
        }

        /// <summary>
        /// Adds all the lines in the New Lines dictionary to the Total Lines dictionary and clears New Lines
        /// </summary>
        public static void UpdateSingleton()
        {
            Instance.Update();
        }

        /// <summary>
        /// Adds the specified string to the Console New Lines
        /// </summary>
        /// <param name="str">The string to add</param>
        public void AddLine(string str)
        {
            lock (this)
            {
                NewLines.Add(LineNumber, str);
                LineNumber++;
            }
            
        }

        /// <summary>
        /// Adds the specified string to the Console New Lines
        /// </summary>
        /// <param name="str">The string to add</param>
        public void AddLine(string str, params object[] args)
        {
            lock (this)
            {
                NewLines.Add(LineNumber, string.Format(str, args));
                LineNumber++;
            }
        }

        /// <summary>
        /// Adds the specified string to the Console New Lines
        /// </summary>
        /// <param name="str">The string to add</param>
        static public void WriteLine(string str)
        {
            Instance.AddLine(str);
        }

        /// <summary>
        /// Adds the specified string to the Console New Lines
        /// </summary>
        /// <param name="str">The string to add</param>
        static public void WriteLine(string str, params object[] args)
        {
            Instance.AddLine(string.Format(str, args));
        }

        /// <summary>
        /// Adds the specified string to the Console New Lines
        /// </summary>
        /// <param name="str">The string to add</param>
        static public void WriteLine(object o)
        {
            Instance.AddLine(o.ToString());
        }

        /// <summary>
        /// Adds a new line to the console
        /// </summary>
        /// <param name="str">The string to add</param>
        static public void WriteLine()
        {
            Instance.AddLine("");
        }



        static Console _instance;
        /// <summary>
        /// Retrieves a static instance of the <see cref="Console"/> class. (A singleton)
        /// </summary>
        public static Console Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new Console();
                }
                return _instance;
            }
        }

    }
}
